from __future__ import division
import os
import re
from random import choice

from django.db import models
from django.contrib import admin
from django.contrib.auth.models import User,Group
from django.contrib.comments.models import Comment


def static_map(*args, **kwargs):
  # lat, lng, size, zoom, maptype
  # Returns a URL to static map with a marker at the centre
  #http://code.google.com/apis/maps/documentation/staticmaps/
  if kwargs['lat'] == None or kwargs['lng'] == None:
    return None
  colour_list = [ "brown", "green", "purple", "yellow", "blue", "gray", "orange", "red", "white" ]
  static_api = "ABQIAAAAhcP5rdJ8gtI2Tvrvo88B3BRheRdRZgitUVyZZmgoSSAEYuewghSEp04JWHUrJoHbRpqILk8pmfDG2g"
  static_map_url =  "http://maps.google.com/staticmap?key="+static_api+"&format=png&sensor=false&"
  #static_map_url += "markers="+str(kwargs['lat'])+","+str(kwargs['lng'])+","+choice(colour_list)+"&"
  static_map_url += "markers="+str(kwargs['lat'])+","+str(kwargs['lng'])+","+'green'+"&"
  static_map_url += "size="+kwargs['size']+"&zoom="+kwargs['zoom']
  try:
    static_map_url +="&maptype="+kwargs['maptype']
  except KeyError:  pass
  return static_map_url

class Icon(models.Model):
  image = models.CharField(max_length=100)
  shadow = models.ForeignKey("self", null=True, blank=True)
  width = models.IntegerField()
  height = models.IntegerField()
  def anchor_x(self): return int(self.width / 2)
  def anchor_y(self): return self.height
  def window_anchor_x(self): return int(self.width / 2)
  def window_anchor_y(self): return 0
  def __unicode__(self): return self.image

class MarkerType(models.Model):
  name = models.CharField(max_length=250)
  icon = models.ForeignKey(Icon)
  class Meta:
      ordering = ('name', 'icon')
  def __unicode__(self): return self.name
  def safename(self):  return re.sub("[^A-Za-z0-9]","",self.name).lower()


class Marker(models.Model):
  active            = models.BooleanField(null=True, default=True, help_text="Is this marker live?")
  lat               = models.FloatField()
  lon               = models.FloatField()
  name              = models.CharField(max_length=250)
  itemtype          = models.ForeignKey(MarkerType)
  link              = models.URLField(blank=True, verify_exists=True, max_length=500, help_text="External website link")
  rateable          = models.BooleanField(default=True,null=True, help_text="Can people rate this object")
  commentable       = models.BooleanField(default=True,null=True, help_text="Can people comment on this object")
  rating            = models.FloatField(null=True, blank=True, help_text="Score out of 10, eg 5.5")
  total_rates       = models.FloatField(null=True, blank=True, help_text="To work out the rating")
  lastupdate        = models.DateTimeField(null=True, blank=True, auto_now=True, help_text="Last time this object was updated")
  public_email      = models.EmailField(blank=True, help_text="Email address of the objects main public contact")
  private_email     = models.EmailField(blank=True, help_text="Email address of the objects main private contact eg for admin usage")
  public_phone      = models.CharField(blank=True, max_length=20, help_text="Public contact phone number for this object")
  private_phone     = models.CharField(blank=True, max_length=20, help_text="Private contact phone number for this object")
  freetext          = models.TextField(blank=True, null=True, help_text="Bulk of the page contents")
  image1            = models.CharField(max_length=100, blank=True, null=True, help_text="Location of image1")
  image2            = models.CharField(max_length=100, blank=True, null=True, help_text="Location of image2")
  image3            = models.CharField(max_length=100, blank=True, null=True, help_text="Location of image3")
  image1_t          = models.CharField(max_length=100, blank=True, null=True, help_text="Location of image1 thumbnail")
  image2_t          = models.CharField(max_length=100, blank=True, null=True, help_text="Location of image2 thumbnail")
  image3_t          = models.CharField(max_length=100, blank=True, null=True, help_text="Location of image3 thumbnail")
  price             = models.CharField(blank=True, null=True, max_length=20)
  thumbnail         = models.CharField(blank=True, null=True, max_length=1000)
  description       = models.CharField(blank=True, null=True, max_length=2000)
  address           = models.CharField(blank=True, null=True, max_length=50)
  creator           = models.CharField(blank=True, null=True, max_length=50, help_text="Who owns the copyright")
  premium           = models.FloatField(blank=True, null=True, help_text="Is a paid for marker")
  owner_user        = models.ForeignKey(User, blank=True, null=True, help_text="Who created this marker")
  owner_group       = models.ManyToManyField(Group, null=True, blank=True) #, null=True, blank=True, help_text="Which group(s) are associated with this marker")
  group_editable    = models.BooleanField(null=True, blank=True, help_text="Can group members edit this marker")
  date_due          = models.DateField(null=True, blank=True, auto_now=False, help_text="Date this item starts.  To allow it to appear on the Coming Soon area")
  date_ends         = models.DateField(null=True, blank=True, auto_now=False, help_text="When these item ends.  If none specified this item will be removed after approx 1 week")
  
  # fields added after initial creation, which use the extra_* DB fields
  slug = models.SlugField(max_length=50, db_column="extra_char_1")
  # define loads of extra fields now so we can use them later
  extra_char_2 = models.CharField(max_length=1000, blank=True,  help_text="Unused")
  extra_char_3 = models.CharField(max_length=1000, blank=True,  help_text="Unused")
  extra_char_4 = models.CharField(max_length=1000, blank=True,  help_text="Unused")
  extra_char_5 = models.CharField(max_length=1000, blank=True,  help_text="Unused")
  extra_char_6 = models.CharField(max_length=1000, blank=True,  help_text="Unused")
  extra_char_7 = models.CharField(max_length=1000, blank=True,  help_text="Unused")
  extra_char_8 = models.CharField(max_length=1000, blank=True,  help_text="Unused")
  extra_char_9 = models.CharField(max_length=1000, blank=True,  help_text="Unused")
  extra_int_1  = models.IntegerField(null=True, blank=True, help_text="Unused")
  extra_int_2  = models.IntegerField(null=True, blank=True, help_text="Unused")
  extra_int_3  = models.IntegerField(null=True, blank=True, help_text="Unused")
  extra_int_4  = models.IntegerField(null=True, blank=True, help_text="Unused")
  extra_int_5  = models.IntegerField(null=True, blank=True, help_text="Unused")
  extra_int_6  = models.IntegerField(null=True, blank=True, help_text="Unused")
  extra_int_7  = models.IntegerField(null=True, blank=True, help_text="Unused")
  extra_int_8  = models.IntegerField(null=True, blank=True, help_text="Unused")
  extra_int_9  = models.IntegerField(null=True, blank=True, help_text="Unused")  
  def __unicode__(self): return self.name
  def staticmap_sm(self):
    return static_map(lat=self.lat, lng=self.lon, size="100x100", zoom="12")
  def staticmap_sm_sat(self):
    return static_map(lat=self.lat, lng=self.lon, size="100x100", zoom="12", maptype="hybrid")
  def staticmap_me(self):
    return static_map(lat=self.lat, lng=self.lon, size="250x250", zoom="13")
  def staticmap_me_sat(self):
    return static_map(lat=self.lat, lng=self.lon, size="250x250", zoom="13", maptype="hybrid")
  def staticmap_lg(self):
    return static_map(lat=self.lat, lng=self.lon, size="300x300", zoom="16")
  def staticmap_lg_sat(self):
    return static_map(lat=self.lat, lng=self.lon, size="300x300", zoom="16", maptype="hybrid")  
  def rating_out_of_five(self):
    if self.rating == None or self.total_rates == None: return 0
    else: return int(self.rating/self.total_rates)
  def rating_width(self):
    return (int(self.rating_out_of_five()) * 18)


 
class PendingMarker(models.Model):
  editors_name    =  models.CharField("Name:",max_length=30, blank=True, help_text="Please enter your name")
  editors_email   =  models.EmailField("Email:",help_text="Your email address")
  marker_name     =  models.CharField("Entry Name:",max_length=30, help_text="Title for this marker")
  marker_type     =  models.ForeignKey(MarkerType, help_text="Select the type of marker.  For example a 'Garage Sale' would be 'Special Event'")
  marker_lat      =  models.FloatField()
  marker_lng      =  models.FloatField()
  marker_descr    =  models.CharField("Description:",max_length=1000, help_text="About this marker")
  date_added      =  models.DateField(auto_now=True, editable=False)
  date_of_event   =  models.DateField("Date of event:",blank=True, null=True, help_text="What is the date of this marker?")
  owner_user      =  models.ForeignKey(User, blank=True, null=True, editable=False)
  def __unicode__(self): return self.marker_name
  def staticmap_sm(self):
    return static_map(lat=self.marker_lat, lng=self.marker_lng, size="100x100", zoom="14")
  def staticmap_me(self):
    return static_map(lat=self.marker_lat, lng=self.marker_lng, size="250x250", zoom="15")
  def staticmap_lg(self):
    return static_map(lat=self.marker_lat, lng=self.marker_lng, size="300x300", zoom="16")
  def staticmap_lg_sat(self):
    return static_map(lat=self.marker_lat, lng=self.marker_lng, size="300x300", zoom="16", maptype="satellite")

# ----- Voting Models

class RatingOnComment(models.Model):
  voted_comment = models.ForeignKey(Comment)
  votes_total   = models.IntegerField(blank=True)
  votes_plus    = models.IntegerField(blank=True, null=True)
  votes_minus   = models.IntegerField(blank=True, null=True)
  def percentage_good(self):
    if self.votes_total == None: return 0
    if self.votes_plus > 0 and self.votes_minus == 0:  self.votes_minus = self.votes_plus
    if self.votes_plus > 0 and self.votes_minus == None:  self.votes_minus = self.votes_plus
    if self.votes_plus == None and self.votes_minus == None: return 0
    if self.votes_plus == None and self.votes_minus != None: return 0
    else:  return int(round((self.votes_plus/self.votes_total)*100))
  def good_vs_bad(self):
    if self.votes_plus == None: self.votes_plus = 0
    if self.votes_minus == None:  self.votes_minus = 0
    return(str(self.votes_plus)+','+str(self.votes_minus))
  def vote_up(self):
    if self.votes_total == None: self.votes_total = 0
    if self.votes_plus == None: self.votes_plus = 0
    self.votes_total += 1
    self.votes_plus  += 1
    return (self.votes_total, self.votes_plus)
  def vote_down(self):
    if self.votes_total == None: self.votes_total = 0
    if self.votes_minus == None: self.votes_minus = 0
    self.votes_total += 1
    self.votes_minus += 1
    return (self.votes_total, self.votes_minus)

class Voter(models.Model):
  voter    = models.ForeignKey(User)
  voteitem = models.ForeignKey(Comment)

class Rater(models.Model):
  rater    = models.ForeignKey(User)
  rateitem = models.ForeignKey(Marker)

#-- Premium users special stuff


class MerchantObject(models.Model):
  related_marker    = models.ForeignKey(Marker)
  active            = models.BooleanField(null=True, default=True, help_text="Is this marker live?")
  lat               = models.FloatField(null=True, blank=True)
  lon               = models.FloatField(null=True, blank=True)
  name              = models.CharField(max_length=250)
  merchantable_type = models.CharField(blank=True, null=True, max_length=250)
  link              = models.URLField(null=True,blank=True, verify_exists=True, max_length=500, help_text="External website link")
  rateable          = models.BooleanField(null=True, help_text="Can people rate this object")
  commentable       = models.BooleanField(null=True, help_text="Can people comment on this object")
  rating            = models.FloatField(null=True, blank=True, help_text="Score out of 10, eg 5.5")
  total_rates       = models.FloatField(null=True, blank=True, help_text="To work out the rating")
  lastupdate        = models.DateTimeField(null=True, blank=True, auto_now=True, help_text="Last time this object was updated")
  public_email      = models.EmailField(blank=True, null=True, help_text="Email address of the objects main public contact")
  private_email     = models.EmailField(blank=True, null=True, help_text="Email address of the objects main private contact eg for admin usage")
  public_phone      = models.CharField(blank=True, null=True, max_length=20, help_text="Public contact phone number for this object")
  private_phone     = models.CharField(blank=True, null=True, max_length=20, help_text="Private contact phone number for this object")
  freetext          = models.TextField(blank=True, null=True, help_text="Bulk of the page contents")
  image1            = models.CharField(max_length=100, blank=True, null=True, help_text="Location of image1")
  thumbnail         = models.CharField(max_length=100, blank=True, null=True, help_text="Location of image1 thumbnail")
  price             = models.CharField(blank=True, null=True, max_length=20)
  description       = models.CharField(blank=True, null=True, max_length=2000)
  address           = models.CharField(blank=True, null=True, max_length=50)
  owner_user        = models.ForeignKey(User, blank=True, null=True, help_text="Who created this marker")
  owner_group       = models.ManyToManyField(Group, null=True, blank=True) #, null=True, blank=True, help_text="Which group(s) are associated with this marker")
  group_editable    = models.BooleanField(null=True, blank=True, help_text="Can group members edit this marker")
  date_due          = models.DateField(null=True, blank=True, auto_now=False, help_text="Date this item starts.  To allow it to appear on the Coming Soon area")
  date_ends         = models.DateField(null=True, blank=True, auto_now=False, help_text="When these item ends.  If none specified this item will be removed after approx 1 week")
  def __unicode__(self): return self.name
  def staticmap_sm(self):
    return static_map(lat=self.lat, lng=self.lon, size="100x100", zoom="12")
  def staticmap_sm_sat(self):
    return static_map(lat=self.lat, lng=self.lon, size="100x100", zoom="12", maptype="hybrid")
  def staticmap_me(self):
    return static_map(lat=self.lat, lng=self.lon, size="250x250", zoom="13")
  def staticmap_me_sat(self):
    return static_map(lat=self.lat, lng=self.lon, size="250x250", zoom="13", maptype="hybrid")
  def staticmap_lg(self):
    return static_map(lat=self.lat, lng=self.lon, size="300x300", zoom="16")
  def staticmap_lg_sat(self):
    return static_map(lat=self.lat, lng=self.lon, size="300x300", zoom="16", maptype="hybrid")  
  def rating_out_of_five(self):
    if self.rating == None or self.total_rates == None: return 0
    else: return int(self.rating/self.total_rates)
  def rating_width(self):
    return (int(self.rating_out_of_five()) * 18)


class MerchantRater(models.Model):
  rater    = models.ForeignKey(User)
  rateitem = models.ForeignKey(MerchantObject)

class Route(models.Model):
  active            = models.BooleanField(null=True, blank=True, default=True)
  name              = models.CharField(blank=True, max_length=250) 
  text              = models.CharField(blank=True, max_length=4000)
  polyline          = models.CharField(blank=True, max_length=4000)
  owner_user        = models.ForeignKey(User, blank=True, null=True)
  owner_group       = models.ManyToManyField(Group, blank=True, null=True)
  lastupdate        = models.DateTimeField(null=True, blank=True, auto_now=True, help_text="Last time this object was updated")
  rateable          = models.BooleanField(default=True,null=True, help_text="Can people rate this object")
  commentable       = models.BooleanField(default=True,null=True, help_text="Can people comment on this object")
  rating            = models.FloatField(null=True, blank=True, help_text="Score out of 10, eg 5.5")
  total_rates       = models.FloatField(null=True, blank=True, help_text="To work out the rating")
  def __unicode__(self): return self.name
  def rating_width(self):
    return (int(self.rating_out_of_five()) * 18)
  def rating_out_of_five(self):
    if self.rating == None or self.total_rates == None: return 0
    else: return int(self.rating/self.total_rates)

class RouteRater(models.Model):
  rater    = models.ForeignKey(User)
  rateitem = models.ForeignKey(Route)
  
class Route_POI(models.Model):
  name              = models.CharField(blank=True, max_length=250)
  related_route     = models.ForeignKey(Route)
  active            = models.BooleanField(null=True,blank=True)
  lat               = models.FloatField(null=True, blank=True)
  lon               = models.FloatField(null=True, blank=True)
  text              = models.CharField(blank=True, max_length=250)
  owner_user        = models.ForeignKey(User, blank=True, null=True)
  lastupdate        = models.DateTimeField(null=True, blank=True, auto_now=True, help_text="Last time this object was updated")  
  def __unicode__(self): return self.name

class Notice(models.Model):
  active            = models.BooleanField(null=True,blank=True)
  text              = models.CharField(max_length=500)
  owner_user        = models.ForeignKey(User)
  lastupdate        = models.DateTimeField(null=True, blank=True, auto_now=True, help_text="Last time this object was updated")
  def __unicode__(self): return self.text
  
try:
  admin.site.register(Icon)
except admin.sites.AlreadyRegistered:
  pass
try:
  admin.site.register(Marker)
except admin.sites.AlreadyRegistered:
  pass
try:
  admin.site.register(MarkerType)
except admin.sites.AlreadyRegistered:
  pass
try:
  admin.site.register(PendingMarker)
except admin.sites.AlreadyRegistered:
  pass
try:
  admin.site.register(RatingOnComment)
except admin.sites.AlreadyRegistered:
  pass
try:
  admin.site.register(Voter)
except admin.sites.AlreadyRegistered:
  pass
try:
  admin.site.register(Rater)
except admin.sites.AlreadyRegistered:
  pass
try:
  admin.site.register(MerchantObject)
except admin.sites.AlreadyRegistered:
  pass
try:
  admin.site.register(MerchantRater)
except admin.sites.AlreadyRegistered:
  pass 
try:
  admin.site.register(Route)
except admin.sites.AlreadyRegistered:
  pass   
try:
  admin.site.register(Route_POI)
except admin.sites.AlreadyRegistered:
  pass 
try:
  admin.site.register(Notice)
except admin.sites.AlreadyRegistered:
  pass 
try:
  admin.site.register(RouteRater)
except admin.sites.AlreadyRegistered:
  pass   
